package com.ailk.cuc.autotestbg.xml.business.impl.ess;

import java.io.IOException;
import java.io.StringReader;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import com.ailk.cuc.autotestbg.common.bean.AutoCaseResultBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoCaseStepBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoStepResultBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoStepResultDetailBGBean;
import com.ailk.cuc.autotestbg.common.business.interf.SendOutComponentInterface;
import com.ailk.cuc.autotestbg.common.exception.DataBaseException;
import com.ailk.cuc.autotestbg.common.utils.LogUtils;
import com.ailk.cuc.autotestbg.common.utils.SpringContextUtil;
import com.ailk.cuc.autotestbg.common.utils.StringFormatUtils;
import com.ailk.cuc.autotestbg.xml.bean.AutoEssDataBean;
import com.ailk.cuc.autotestbg.xml.bean.AutoEssInterfaceBean;
import com.ailk.cuc.autotestbg.xml.exception.EssSendOutException;
import com.ibatis.sqlmap.client.SqlMapClient;

public class EssSendOutComponentImpl implements SendOutComponentInterface {

	private static Log logger = LogUtils.getLogger(EssSendOutComponentImpl.class.getName());
	public void sendOutInfo(Map<String, Object> argMapIn,Map<String,Object> argMapOut) throws EssSendOutException {
		try {
			AutoEssDataBean essDataBean = (AutoEssDataBean)argMapIn.get("essDataBean");
			
			SqlMapClient sqlMapClient = (SqlMapClient)SpringContextUtil.getBean("sqlMapClient");
			
			AutoCaseResultBGBean caseResultBGBean = (AutoCaseResultBGBean)argMapIn.get("caseResultBGBean");
			AutoCaseStepBGBean caseStepBean = (AutoCaseStepBGBean) argMapIn.get("caseStepBean");
			AutoStepResultBGBean stepResultBGBean = new AutoStepResultBGBean();
			AutoStepResultDetailBGBean stepResultDetailBGBean =  new AutoStepResultDetailBGBean();
			
			//写入结果表的步骤，分为如下几步
			//1.发送之前，先写入结果表 
			insertStepResultBGBean(stepResultBGBean, caseResultBGBean, caseStepBean, sqlMapClient);
			
			AutoEssInterfaceBean essInterfaceBean = null;
			try {
				essInterfaceBean = (AutoEssInterfaceBean)sqlMapClient.queryForObject("xml_ess_ecs_assembly.getEssInterfaceBean",essDataBean);
			} catch (SQLException e) {
				logger.error("EssSendOutComponentImpl.sendOutInfo方法异常");
				logger.error(e.getMessage());
				throw new DataBaseException("ESS发送报文之前，获取essInterface数据操作异常");
			}
			
			String essMessageXml = (String)argMapIn.get(essDataBean.getInterfaceId()+"_request_"+"essMessageXml");

			logger.info("ESS发送报文开始");
			String essResponseXml = sendOutEssRequestMessage(essInterfaceBean,essMessageXml);
			logger.info("ESS接收报文结束 ");
			
			argMapIn.put(essDataBean.getInterfaceId()+"_response_"+"essMessageXml", essResponseXml);
			
			
			//处理接收到的报文，主要是做验证使用
			String expectResult = essDataBean.getExpectResult();
			checkEssResponseIsRight(expectResult, essResponseXml,stepResultDetailBGBean);
			String handleData = StringFormatUtils.formatLong("%1$06d", caseStepBean.getTestCaseId())+" "+essDataBean.getInterfaceId()+essMessageXml;
			stepResultDetailBGBean.setHandleData(handleData.length()>3900?handleData.substring(0, 3900):handleData);
			
			//2.接收到返回的报文，并经过处理之后，写入StepResultDetail表
			insertStepResultDetailBGBean(stepResultDetailBGBean, stepResultBGBean, sqlMapClient);
			
			//3.更新stepResultBGBean
			updateStepResultBGBean(stepResultBGBean, stepResultDetailBGBean, sqlMapClient);
			
			//获取下一个caseStep
			AutoCaseStepBGBean nextCaseStepBean = null;
			AutoEssDataBean nextEssDataBean = null;
			try {
				nextCaseStepBean = (AutoCaseStepBGBean)sqlMapClient.queryForObject("xml_ess_ecs_sendout.getNextCaseStepByUp",caseStepBean);
				if(nextCaseStepBean != null){
					String dataId = nextCaseStepBean.getInputDataId()+"";
					nextEssDataBean = (AutoEssDataBean)sqlMapClient.queryForObject("xml_ess_ecs_assembly.getEssDatabean",dataId);
				}
			} catch (SQLException e) {
				logger.error("EssSendOutComponentImpl.sendOutInfo方法异常");
				logger.error(e.getMessage());
				throw new DataBaseException("ESS发送报文完成，获取下一步数据操作异常");
			}
			argMapIn.put("essDataBean", nextEssDataBean);
			argMapIn.put("caseStepBean", nextCaseStepBean);
			
			//4.更新caseResultBGBean
			updateCaseResultBGBean(caseResultBGBean, sqlMapClient);
			
			//将入参传递给出参
			argMapOut.putAll(argMapIn);
		} catch (DataBaseException e) {
			logger.error("ESS发送报文发生异常");
			logger.error(e.getMessage());
			throw new EssSendOutException("发送报文时发生数据库操作异常");
		}
	}

	public String sendOutEssRequestMessage(AutoEssInterfaceBean essInterfaceBean,String essMessageXml){
		String essResponseXml = "";
		String url = essInterfaceBean.getAddress().toString();

		NameValuePair nameValue = new NameValuePair("xmlmsg", essMessageXml);
		PostMethod post = new PostMethod(url);

		post.setRequestBody(new NameValuePair[]{nameValue});
		HttpClient client = new HttpClient();
		client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8") ;
		client.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
		client.getHttpConnectionManager().getParams().setSoTimeout(30000);

		logger.info("将ESS报文转发至" + url);
		try {
			client.executeMethod(post);
			essResponseXml = post.getResponseBodyAsString();
			
			essResponseXml = URLDecoder.decode(essResponseXml, "UTF-8");
		} catch (HttpException e) {
			// 发生致命的异常，可能是协议不对或者返回的内容有问题
			logger.error("HTTP异常！");
			logger.error(e.getMessage());
			essResponseXml = "00040005";
			// e.printStackTrace();
		} catch (IOException e) {
			// 发生网络异常
			logger.error("网络异常！");
			logger.error(e.getMessage());
			essResponseXml = "00040006";
		}

		logger.info("接收到响应报文:"+essResponseXml);

		return essResponseXml;
	}
	
	
	public void insertStepResultBGBean(AutoStepResultBGBean stepResultBGBean, AutoCaseResultBGBean caseResultBGBean,AutoCaseStepBGBean caseStepBean,SqlMapClient sqlMapClient) throws DataBaseException{
		
		stepResultBGBean.setTaskId(caseResultBGBean.getTaskId());
		stepResultBGBean.setTestNo(caseResultBGBean.getTestNo());
		stepResultBGBean.setSeqId(caseStepBean.getSeqId());
		stepResultBGBean.setStepName(caseStepBean.getStepName());
		
		try {
			sqlMapClient.insert("common_result.insertStepResultBGBean",stepResultBGBean);
		} catch (SQLException e) {
			logger.error("EssSendOutComponentImpl.insertStepResultBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ESS发送报文插入StepResult数据操作异常");
		}
	}
	
	public void insertStepResultDetailBGBean(AutoStepResultDetailBGBean stepResultDetailBGBean ,AutoStepResultBGBean stepResultBGBean, SqlMapClient sqlMapClient) throws DataBaseException{
		
		stepResultDetailBGBean.setTaskId(stepResultBGBean.getTaskId());
		stepResultDetailBGBean.setTestNo(stepResultBGBean.getTestNo());
		stepResultDetailBGBean.setSeqId(stepResultBGBean.getSeqId());
		stepResultDetailBGBean.setType(2+"");
		
		try {
//			long serialId = (Long)sqlMapClient.queryForObject("common_result.getStepResultDetailSerialIdBySeq");
//			stepResultDetailBGBean.setSerialId(serialId);
			sqlMapClient.insert("common_result.insertStepResultDetailBGBean",stepResultDetailBGBean);
		} catch (SQLException e) {
			logger.error("EssSendOutComponentImpl.insertStepResultDetailBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ESS发送报文插入StepResultDetail数据操作异常");
		}
	}
	
	public void checkEssResponseIsRight(String expectResult,String essResponseXml,AutoStepResultDetailBGBean stepResultDetailBGBean){
		boolean right = true;
		StringBuilder realResult = new StringBuilder("");
		SAXReader reader = new SAXReader();

		stepResultDetailBGBean.setExpectData(expectResult==null?"":expectResult);
		
		logger.info("expectResult : "+expectResult);
		
		try {
			if(expectResult!=null && !"".equals(expectResult)){

				org.dom4j.Document doc1 = reader.read(new InputSource(new StringReader(essResponseXml)));

				logger.info("essResponseXml : "+essResponseXml);
				Node SvcContCode = doc1.selectSingleNode("//SvcCont");
				
				logger.info("SvcContCode is null : "+(SvcContCode == null ? true : false));

				if(SvcContCode != null){
					String responseInfo = SvcContCode.getText();
					
					if(responseInfo != null && !"".equals(responseInfo)){
						
						org.dom4j.Document doc2 = reader.read(new InputSource(new StringReader(responseInfo)));
						
						String[] expectResultArray = expectResult.split("\\^");
						for(String expectResultStr : expectResultArray){
							
							String[] expectResultKeyAndValue = expectResultStr.split("=");
							String expectResultKey = "";
							String expectResultValue = "";
							if(expectResultKeyAndValue.length != 2){
								expectResultValue = expectResultKeyAndValue[0];
								expectResultKey = expectResultKeyAndValue[0];
								right = false;
							}else{
								expectResultKey = expectResultKeyAndValue[0];
								expectResultValue = expectResultKeyAndValue[1];
							}
							
							String expectResultKeyTemp = expectResultKey.replaceAll("\\.", "/");
							logger.info("expectResultKeyTemp : "+expectResultKeyTemp);
							
							Node respCodeNode= doc2.selectSingleNode(expectResultKeyTemp);
							logger.info("respCodeNode is null : "+respCodeNode == null ? true : false);
							
							if(respCodeNode != null){
								String respCodeValue = respCodeNode.getText();
								logger.info("respCodeValue  : "+respCodeValue == null ? "" : respCodeValue);
								if(right){
									if(respCodeValue != null){
										right = expectResultValue.indexOf(respCodeValue.trim())!=-1?true:false; 
									}else{
										right = false;
									}
								}
								realResult.append(expectResultKeyTemp).append("=").append(respCodeValue == null ? "recv null" : respCodeValue).append(";");
							}else{
								right = false;
								realResult.append(expectResultKeyTemp).append("=").append("recv null").append(";");
							}
							
						}
					}else{
						right = false;
						realResult.append("SvcCont'text is null");
					}

				}else{
					right = false;
					realResult.append("The Resp Xml is Null Or unavailable :[]").append(";");
				}
			}else{
				//如果是没有比对结果值，则默认比对成功
				right = true;
			}

			stepResultDetailBGBean.setStatus(right?"1":"2");
			stepResultDetailBGBean.setRealData(realResult.toString().replaceAll("/", "."));
		} catch (DocumentException e) {
			logger.error("解析返回的XML报文发生异常");
			logger.error(e.getMessage());
			e.printStackTrace();
			stepResultDetailBGBean.setStatus("2");
			stepResultDetailBGBean.setRealData("java parser response message exception");
		}
	}
	
	public void updateStepResultBGBean(AutoStepResultBGBean stepResultBGBean,AutoStepResultDetailBGBean stepResultDetailBGBean,SqlMapClient sqlMapClient) throws DataBaseException{
		
		if("1".equals(stepResultDetailBGBean.getStatus())){
			stepResultBGBean.setIsRight("Y");
			stepResultBGBean.setErrorDesc("");
		}else{
			stepResultBGBean.setIsRight("N");
			stepResultBGBean.setErrorDesc(stepResultDetailBGBean.getRealData());
		}
		try {
			sqlMapClient.update("common_result.updateStepResultBGBean",stepResultBGBean);
		} catch (SQLException e) {
			logger.error("EssSendOutComponentImpl.updateStepResultBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ESS发送报文更新StepResult数据操作异常");
		}
	}
	
	public void updateCaseResultBGBean(AutoCaseResultBGBean caseResultBGBean,SqlMapClient sqlMapClient) throws DataBaseException{
		
		caseResultBGBean.setOverStepNum(caseResultBGBean.getOverStepNum()+1);
		try {
			sqlMapClient.update("common_result.updateCaseResultBGBean",caseResultBGBean);
		} catch (SQLException e) {
			logger.error("EssSendOutComponentImpl.updateCaseResultBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ESS发送报文更新CaseResult数据操作异常");
		}
	}
}
